package curd

import (
	"gitee.com/miajio/generator-code-for-go/pkg/utils"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

// 获取数据库连接
func GetConn() (*sqlx.DB, error) {
	db, err := sqlx.Open("mysql", "root:123456@tcp(localhost:3306)/miajiodb?charset=utf8mb4&parseTime=true")
	return db, err
}

// 关闭数据库连接
func CloseConn(db *sqlx.DB) {
	db.Close()
}

// 获取数据库对应表字段、类型、主键、注释
func GetTableInfo(db *sqlx.DB, tableName string) ([]*TableColumn, error) {
	var tableInfos []*TableColumn
	var err error
	tableInfos, err = GetTableColumn(db, tableName)
	if err != nil {
		return nil, err
	}
	return tableInfos, nil
}

// TableColumn 数据库字段信息
type TableColumn struct {
	Field   string `json:"field"`   // 字段名称
	Type    string `json:"type"`    // 字段类型
	Key     string `json:"key"`     // 是否为键
	Default string `json:"default"` // 默认值
	IsNull  bool   `json:"isNull"`  // 是否允许为空
	Comment string `json:"comment"` // 字段注释
}

const (
	descSql = `SELECT COL.COLUMN_NAME    as 'Field',
					COL.COLUMN_TYPE    	 as 'Type',
					COL.COLUMN_KEY       as 'Key',
					COL.COLUMN_DEFAULT   as 'Default',
					COL.IS_NULLABLE      as 'Null',
					COL.COLUMN_COMMENT   as 'Comment'
				FROM INFORMATION_SCHEMA.COLUMNS COL
					WHERE COL.TABLE_NAME = ?`
)

// GetTableColumn 获取表字段信息
func GetTableColumn(db *sqlx.DB, tableName string) ([]*TableColumn, error) {
	var tableInfos []*TableColumn
	var err error

	// 依据表名获取表字段信息
	rows, err := db.Query(descSql, tableName)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		var tableInfo TableColumn
		var isNull string
		err = rows.Scan(&tableInfo.Field, &tableInfo.Type, &tableInfo.Key, &tableInfo.Default, &isNull, &tableInfo.Comment)
		if err != nil {
			return nil, err
		}
		if isNull == "YES" {
			tableInfo.IsNull = true
		}

		tableInfos = append(tableInfos, &tableInfo)
	}
	return tableInfos, nil
}

// GeneratorStruct 依据表名及表字段信息生成对应的结构体
func GeneratorStruct(tableName string, tableInfos []*TableColumn) string {
	var structStr string
	structStr = "type " + utils.ToCamelCase(tableName) + " struct {\n"
	for _, tableInfo := range tableInfos {
		structStr += "\t" + utils.ToCamelCase(tableInfo.Field) + " "
		if tableInfo.IsNull {
			structStr += "*"
		}
		structStr += dbTypeToGoType(tableInfo.Type)

		if tableInfo.Key == "PRI" {
			structStr += " `pri:\"true\" db:\"" + tableInfo.Field + "\"`"
		} else {
			structStr += " `db:\"" + tableInfo.Field + "\"`"
		}

		if tableInfo.Comment != "" {
			structStr += " // " + tableInfo.Comment
		}
		structStr += "\n"
	}
	structStr += "}"
	return structStr
}
